package com.todod.base.module.infra.service.file;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.todod.base.framework.common.pojo.PageResult;
import com.todod.base.framework.common.util.io.FileUtils;
import com.todod.base.framework.common.util.object.BeanUtils;
import com.todod.base.module.infra.controller.admin.file.vo.file.FileCreateReqVO;
import com.todod.base.module.infra.controller.admin.file.vo.file.FilePageReqVO;
import com.todod.base.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO;
import com.todod.base.module.infra.dal.dataobject.file.FileConfigDO;
import com.todod.base.module.infra.dal.dataobject.file.FileDO;
import com.todod.base.module.infra.dal.mysql.file.FileMapper;
import com.todod.base.module.infra.enums.untils.MinIoUtils;
import com.todod.base.module.infra.framework.file.core.client.FileClient;
import com.todod.base.module.infra.framework.file.core.client.s3.FilePresignedUrlRespDTO;
import com.todod.base.module.infra.framework.file.core.utils.FileTypeUtils;
import jakarta.annotation.Resource;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.todod.base.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.todod.base.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS;

/**
 * 文件 Service 实现类
 *
 * @author admin
 */
@Service
public class FileServiceImpl implements FileService {

    @Resource
    private FileConfigService fileConfigService;

    @Resource
    private FileMapper fileMapper;

    @Value("${file.visit}")
    private String visi;
    @Value("${file.visithttps}")
    private String visiHttps;
    // 存储桶名称
    @Value("${minio.bucketName}")
    private String bucketName;
    @Autowired
    private MinIoUtils minIoUtils;

    @Override
    public PageResult<FileDO> getFilePage(FilePageReqVO pageReqVO) {
        return fileMapper.selectPage(pageReqVO);
    }

    @Override
    @SneakyThrows
    public String createFile(String name, String path, byte[] content) {
        // 计算默认的 path 名
        String type = FileTypeUtils.getMineType(content, name);
        if (StrUtil.isEmpty(path)) {
            path = FileUtils.generatePath(content, name);
        }
        // 如果 name 为空，则使用 path 填充
        if (StrUtil.isEmpty(name)) {
            name = path;
        }

        // 上传到文件存储器
        FileClient client = fileConfigService.getMasterFileClient();
        Assert.notNull(client, "客户端(master) 不能为空");
        String url = client.upload(content, path, type);

        // 保存到数据库
        FileDO file = new FileDO();
        file.setConfigId(client.getId());
        file.setName(name);
        file.setPath(path);
        file.setUrl(url);
        file.setType(type);
        file.setSize(content.length);
        fileMapper.insert(file);
        return url;
    }

    @Override
    public Long createFile(FileCreateReqVO createReqVO) {
        FileDO file = BeanUtils.toBean(createReqVO, FileDO.class);
        fileMapper.insert(file);
        return file.getId();
    }

    @Override
    public void deleteFile(Long id) throws Exception {
        // 校验存在
        FileDO file = validateFileExists(id);

        // 从文件存储器中删除
        FileClient client = fileConfigService.getFileClient(file.getConfigId());
        Assert.notNull(client, "客户端({}) 不能为空", file.getConfigId());
        client.delete(file.getPath());

        // 删除记录
        fileMapper.deleteById(id);
    }

    private FileDO validateFileExists(Long id) {
        FileDO fileDO = fileMapper.selectById(id);
        if (fileDO == null) {
            throw exception(FILE_NOT_EXISTS);
        }
        return fileDO;
    }

    @Override
    public byte[] getFileContent(Long configId, String path) throws Exception {
        FileClient client = fileConfigService.getFileClient(configId);
        Assert.notNull(client, "客户端({}) 不能为空", configId);
        return client.getContent(path);
    }

    @Override
    public FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception {
        FileClient fileClient = fileConfigService.getMasterFileClient();
        FilePresignedUrlRespDTO presignedObjectUrl = fileClient.getPresignedObjectUrl(path);
        return BeanUtils.toBean(presignedObjectUrl, FilePresignedUrlRespVO.class,
                object -> object.setConfigId(fileClient.getId()));
    }

    @Override
    @SneakyThrows
    public FileDO newCreateFile(MultipartFile file, String path, byte[] content) {
        String type = FileTypeUtils.getMineType(content, file.getOriginalFilename());
        String name = file.getOriginalFilename();

        String url = minIoUtils.upload(file, bucketName, null);

        // 保存到数据库
        FileDO file1 = new FileDO();
        file1.setConfigId(22l);
        file1.setName(name);
        file1.setPath(url);
        file1.setUrl(visiHttps+url);
        file1.setType(type);
        file1.setSize(content.length);
        fileMapper.insert(file1);
        return file1;
    }
    @Override
    public FileDO selectById(Long id) {
        return fileMapper.selectById(id);
    }

    @Override
    public void updateFileRealtion(List<FileCreateReqVO> list) {
        // 1、根据表名、表id、文件类型获取其下的所有的文件
        List<FileDO> fileList = this.getListByForeignTableInfo(list.get(0).getForeignTableId(), list.get(0).getForeignTable_name(), list.get(0).getForeignFileType()); //

//        for (FileCreateReqVO item: list) {
//            FileDO updateFile = BeanUtils.toBean(item, FileDO.class);
//            List<FileDO> dList = fileList.stream().filter(file -> file.getId() == item.getId()).collect(Collectors.toList());
//            updateFile.setName(dList.get(0).getName());
//            updateFile.setConfigId(dList.get(0).getConfigId());
//            updateFile.setPath(dList.get(0).getPath());
//            updateFile.setUrl(dList.get(0).getUrl());
//            updateFile.setType(dList.get(0).getType());
//            updateFile.setSize(dList.get(0).getSize());
//            fileMapper.updateById(updateFile);
//        }
        fileList.stream().forEach(item -> {
            FileDO updateFile = BeanUtils.toBean(item, FileDO.class);
            List<FileDO> dList = fileList.stream().filter(file -> file.getId() == item.getId()).collect(Collectors.toList());
            updateFile.setName(dList.get(0).getName());
            updateFile.setConfigId(dList.get(0).getConfigId());
            updateFile.setPath(dList.get(0).getPath());
            updateFile.setUrl(dList.get(0).getUrl());
            updateFile.setType(dList.get(0).getType());
            updateFile.setSize(dList.get(0).getSize());
            fileMapper.updateById(updateFile);
        });

    }

    @Override
    public List<FileDO> getListByForeignTableInfo(Long foreignTableId, String foreignTableName, String foreignFileType) {
        return fileMapper.getListByForeignTableInfo(foreignTableId, foreignTableName, foreignFileType);
    }

}
